package top.abilities.util.util;

import org.apache.commons.lang.ObjectUtils;
import org.apache.velocity.VelocityContext;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;

import static top.abilities.util.util.StringUtil.lineToHump;


/**
 * 代码生成类
 */
public class MybatisGeneratorForRenrenUtil {

	// generatorConfig模板路径
	private static String generatorConfig_vm = "/template/RenrenGeneratorConfig.vm";
	// Service模板路径
	private static String service_vm = "/template/RenrenService.vm";
	// ServiceMock模板路径
	private static String serviceMock_vm = "/template/RenrenServiceMock.vm";
	// ServiceImpl模板路径
	private static String serviceImpl_vm = "/template/RenrenServiceImpl.vm";

	/**
	 * 根据模板生成generatorConfig.xml文件
	 * @param jdbc_driver   驱动路径
	 * @param jdbc_url      链接
	 * @param jdbc_username 帐号
	 * @param jdbc_password 密码
	 * @param module        项目模块
	 * @param database      数据库
	 * @param table_prefix  表前缀
	 * @param package_name  包名
	 */
	public static void generator(
			String jdbc_driver,
			String jdbc_url,
			String jdbc_username,
			String jdbc_password,
			String module,
			String database,
			String table_prefix,
			String package_name,
			Map<String, String> last_insert_id_tables) throws Exception{

		generatorConfig_vm = MybatisGeneratorForRenrenUtil.class.getResource(generatorConfig_vm).getPath().replaceFirst("/", "");
		service_vm = MybatisGeneratorForRenrenUtil.class.getResource(service_vm).getPath().replaceFirst("/", "");
		serviceMock_vm = MybatisGeneratorForRenrenUtil.class.getResource(serviceMock_vm).getPath().replaceFirst("/", "");
		serviceImpl_vm = MybatisGeneratorForRenrenUtil.class.getResource(serviceImpl_vm).getPath().replaceFirst("/", "");

		String targetProject =  module + "-admin";
		String basePath = MybatisGeneratorForRenrenUtil.class.getResource("/").getPath().replace("/target/classes/", "").replace("fesco-mybatis-generator", "").replaceFirst("/", "");
		String generatorConfig_xml = MybatisGeneratorForRenrenUtil.class.getResource("/").getPath().replace("/target/classes/", "") + "/src/main/resources/generatorConfig_renren.xml";
		targetProject = basePath + targetProject;
		database="dbo";
		StringBuffer tableNameCondition=new StringBuffer();
		tableNameCondition.append("(");
		Arrays.asList(table_prefix.split(",")).forEach(e->{
			tableNameCondition.append("table_name LIKE '");
			tableNameCondition.append(e);
			tableNameCondition.append("_%' ");
			tableNameCondition.append(" or ");

		});
		tableNameCondition.append(");");

		String sql = "SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = '" + database + "' AND "+tableNameCondition.toString();
		//String sql = " SELECT Name TABLE_NAME FROM SysObjects Where XType='U'  AND Name LIKE '"+table_prefix+"_%';";
		sql=sql.replace("or )",")");
		//实体、service后缀
		String fixHou="Ren";
		System.out.println("========== 开始生成generatorConfig.xml文件 ==========");
		List<Map<String, Object>> tables = new ArrayList<>();
		try {
			VelocityContext context = new VelocityContext();
			Map<String, Object> table;

			// 查询定制前缀项目的所有表
			JdbcUtil jdbcUtil = new JdbcUtil(jdbc_driver, jdbc_url, jdbc_username, AESUtil.AESDecode(jdbc_password));
			List<Map> result = jdbcUtil.selectByParams(sql, null);
			for (Map map : result) {
				//System.out.println(map.get("TABLE_NAME"));
				System.out.println(map.get("table_name"));
				if(isExcludeTable((String) map.get("table_name"))){
					System.out.println("ExcludeTable:"+map.get("table_name"));
					continue;
				}
				table = new HashMap<>();
				table.put("table_name", map.get("table_name"));
				table.put("model_name", lineToHump(ObjectUtils.toString(map.get("table_name")))+fixHou);
				tables.add(table);
			}
			jdbcUtil.release();

			//以关键字命名的数据表及字段
			Map<String, List<String>> keys=new HashMap<>();
			keys.put("T_Fes_User_Ext",Arrays.asList("native"));

			String targetProject_sqlMap = basePath + module + "-admin";
			context.put("tables", tables);
			context.put("generator_javaModelGenerator_targetPackage", package_name +".dao.model");
			context.put("generator_sqlMapGenerator_targetPackage", package_name +".dao.mapper");
			context.put("generator_javaClientGenerator_targetPackage", package_name +".dao.mapper");
			context.put("targetProject", targetProject);
			context.put("targetProject_sqlMap", targetProject_sqlMap);
			context.put("generator_jdbc_password", AESUtil.AESDecode(jdbc_password));
			context.put("last_insert_id_tables", last_insert_id_tables);
			context.put("specialTableKeys",keys);
			VelocityUtil.generate(generatorConfig_vm, generatorConfig_xml, context);
			// 删除旧代码
			deleteDir(new File(targetProject + "/src/main/java/" + package_name.replaceAll("\\.", "/") + "/dao/model"));
			deleteDir(new File(targetProject + "/src/main/java/" + package_name.replaceAll("\\.", "/") + "/dao/mapper"));
			deleteDir(new File(targetProject_sqlMap + "/src/main/java/" + package_name.replaceAll("\\.", "/") +"/dao/mapper"));
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("========== 结束生成generatorConfig.xml文件 ==========");

		System.out.println("========== 开始运行MybatisGenerator ==========");
		List<String> warnings = new ArrayList<>();
		File configFile = new File(generatorConfig_xml);
		ConfigurationParser cp = new ConfigurationParser(warnings);
		Configuration config = cp.parseConfiguration(configFile);
		DefaultShellCallback callback = new DefaultShellCallback(true);
		MyBatisGeneratorExtends myBatisGenerator = new MyBatisGeneratorExtends(config, callback, warnings);
		myBatisGenerator.generate(null);
		for (String warning : warnings) {
			System.out.println(warning);
		}
		System.out.println("========== 结束运行MybatisGenerator ==========");

		System.out.println("========== 开始生成Service ==========");
		String ctime = new SimpleDateFormat("yyyy/M/d").format(new Date());
		String servicePath = basePath  + module + "-admin" + "/src/main/java/" + package_name.replaceAll("\\.", "/") + "/service";
		String serviceImplPath = basePath  + module + "-admin" + "/src/main/java/" + package_name.replaceAll("\\.", "/") +"/service/impl";
		for (int i = 0; i < tables.size(); i++) {
			String model = lineToHump(ObjectUtils.toString(tables.get(i).get("table_name")))+fixHou;
			String service = servicePath + "/" + model + "Service.java";
			String serviceMock = servicePath + "/" + model + "ServiceMock.java";
			String serviceImpl = serviceImplPath + "/" + model + "ServiceImpl.java";
			// 生成service
			File serviceFile = new File(service);
			if (!serviceFile.exists()) {
				VelocityContext context = new VelocityContext();
				context.put("package_name", package_name);
				context.put("model", model);
				context.put("ctime", ctime);
//				context.put("subMoudle",subModule);
				VelocityUtil.generate(service_vm, service, context);
				System.out.println(service);
			}
			// 生成serviceMock
			/*File serviceMockFile = new File(serviceMock);
			if (!serviceMockFile.exists()) {
				VelocityContext context = new VelocityContext();
				context.put("package_name", package_name);
				context.put("model", model);
				context.put("ctime", ctime);
				VelocityUtil.generate(serviceMock_vm, serviceMock, context);
				System.out.println(serviceMock);
			}*/
			// 生成serviceImpl
			File serviceImplFile = new File(serviceImpl);
			if (!serviceImplFile.exists()) {
				VelocityContext context = new VelocityContext();
				context.put("mapper", StringUtil.toLowerCaseFirstOne(model));
				context.put("ctime", ctime);
				context.put("package_name", package_name);
				context.put("model", model);
//				context.put("subMoudle",subModule);
				VelocityUtil.generate(serviceImpl_vm, serviceImpl, context);
				System.out.println(serviceImpl);
			}
		}
		System.out.println("========== 结束生成Service ==========");

		System.out.println("========== 开始生成Controller ==========");
		System.out.println("========== 结束生成Controller ==========");
	}

	// 递归删除非空文件夹
	public static void deleteDir(File dir) {
		if (dir.isDirectory()) {
			File[] files = dir.listFiles();
			for (int i = 0; i < files.length; i++) {
				deleteDir(files[i]);
			}
		}
		dir.delete();
	}

	/**
	 * @Description:判断是否要去除表  false为否，true是
	 * @Param: []
	 * @Return boolean
	 * @Author abilites
	 * @Date 2018/1/30 9:32
	 */
	public static boolean isExcludeTable(String tableName){
		List<String> tables=new ArrayList<>();
		tables.add("T_Exm_Jigou_test");
		tables.add("tuv2016all");
		tables.add("tuv2016allNew");
		tables.add("tuv2016mobile");
		tables.add("T_Exm_User201608021703");
		tables.add("T_Exm_words_fesnewtest");
		tables.add("T_Gds_Dan_PayCode_Ins");
		tables.add("test");
		tables.add("T_Gds_Dan_PayCode_Ins_Tail");
		tables.add("T_Sys_PhoneCode");
		tables.add("T_Sys_QrCode");
		tables.add("T_Sys_ServiceCenter");
		tables.add("T_Yy_plan");
		tables.add("T_Yy_record");
		tables.add("temp_Sohu");
		tables.add("zhuanhua");
		tables.add("X_SENDS");
		tables.add("T_SendMsgTel");
		tables.add("T_Sys_IdCardInfo");
		tables.add("T_Gds_Book");
		tables.add("T_MoHe_Discount");
		tables.add("T_MoHe_Exception");
		tables.add("T_MoHe_Order");
		tables.add("T_MoHe_Product");
		tables.add("T_MoHe_Refund");


		tables.add("T_Fes_Fls_Pro_FenType");
		tables.add("T_Gds_Dan_Rate");
		tables.add("T_Gds_Dan_Report_Fapiao");
		tables.add("T_Gds_Dan_Report");
		tables.add("T_Gds_Dan_Report_Record");
		tables.add("T_Gds_Rate");
		tables.add("T_Rate_Code");
		tables.add("T_Sohu_Push_Message");
        tables.add("T_Gds_Pub_Col_ins");
        tables.add("T_Gds_Pub_Col_ins_Tail");

        tables.add("T_GdsDan_FinanceData_ins_Tail");
		tables.add("T_GdsDan_FinanceData_ins");
		tables.add("T_MoHe_Wx_Pay");
		tables.add("T_Sys_Articles_ModeType");
		tables.add("T_Code_Addr_Change_Note");
		tables.add("T_Sys_Queue");
		tables.add("T_Fes_Fls_AuthAccount");
		tables.add("T_Fes_Admin_Role_Tail");
		tables.add("T_Fes_Admin_Role");
		tables.add("T_Fes_Addr");
		tables.add("T_Fes_BenefitsProductInfo");
		tables.add("T_Fes_FlsOfMgr");
		tables.add("T_Fes_Menu_Fls");
		tables.add("T_Fes_OneCardIns_Base");
		tables.add("T_Fes_User_Accountx");
		tables.add("T_Fes_Admin_Manager");
		tables.add("T_Fes_Admin_Menu");
		tables.add("T_Fes_Admin_Oper_Note");
		tables.add("T_Fes_BenefitsProductFileInfo");
		tables.add("T_Fes_Business_Fls");
		tables.add("T_Fes_Fls_Banner");
		tables.add("T_Fes_Admin_Part");
		tables.add("T_Fes_Audit");
		tables.add("T_Fes_BusinessOfMgr");
		tables.add("T_Fes_Fls_Link");
		tables.add("T_Fes_Menu");
		tables.add("T_Fes_Question");
		tables.add("T_Fes_User_Bak");
		tables.add("T_Fes_User_Check");
		tables.add("T_Fes_User_Check_Note");

		tables.add("T_fes_user_20190422");
		tables.add("T_Fes_User_DELETE_2019_03_15");
		tables.add("T_Fes_User_PreSys");
		tables.add("T_Fes_User_PreSys_Temp");


		tables.add("t_fes_dept_statistic_copy1");
		tables.add("T_Fes_user_Fennote_129");
		tables.add("T_Fes_Fls_Notice_129");

		tables.add("T_Fes_user_Fennote_129");
		tables.add("t_fes_fls_notice_picture_129");

		tables.add("T_Fes_Comment");
		tables.add("T_Fes_dept_Fennote_129");
		tables.add("T_Fes_FenNote_Complex");
		tables.add("T_Fes_Fennote_Log");
		tables.add("T_Fes_Fls_Ext_copy1");
		tables.add("t_fes_fls_gap_notice_type_copy1");
		tables.add("T_Fes_Send_Gift");
		tables.add("T_fes_ThumbsUpNum");
		tables.add("T_Fes_User_Part");

		tables.add("T_ExImportFiles");
		tables.add("T_Code_ProvCity_mi");
		tables.add("T_Sys_Mails");
		tables.add("T_Gds_SellAfter_RefundBank_Ins");
		tables.add("T_Sch_Plan_User");
		tables.add("T_Act_Abdate");
		tables.add("T_Gds_Area");
		tables.add("T_MicrAct_PromoCode");
		tables.add("T_MicrAct_Active");
		tables.add("T_MicrAct_Registration");
		tables.add("T_MicrAct_Reginput_Extend");
		tables.add("T_MicrAct_Files");
		tables.add("T_MicrAct_Card");
		tables.add("T_Gds_Col_Def_TEMP");
		tables.add("T_Gds_Cang");
		tables.add("T_Fes_Userverify");


		for (String table : tables) {
			if(table.equalsIgnoreCase(tableName)){
				return true;
			}
		}
		return false;
	}
}
